package com.example.demo.core.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.example.demo.core.annotations.ApiNotNull;
import com.example.demo.core.exception.ProgramException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.io.ClassPathResource;

import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author meiyaSQL
 * @Date 2019/8/28
 */
@Slf4j
public class JsonUtil {

    /**
     * 把json文件转成对象
     *
     * @param path json文件路径
     * @param type 转换的类格式
     */
    public static <T> T jsonFileToObject(String path, Class<T> type) {
        try {
            return JSONObject.parseObject(
                    IOUtils.toString(
                            new InputStreamReader(
                                    new ClassPathResource(path).getInputStream(),
                                    StandardCharsets.UTF_8)),
                    type);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 把json文件转成List
     *
     * @param path json文件路径
     * @param type 转换的类格式
     */
    public static <T> List<T> jsonFileToArray(String path, Class<T> type) {
        if (StringUtils.isBlank(path)) {
            throw new ProgramException("路径为空");
        }
        try {
            return JSONArray.parseArray(
                    IOUtils.toString(
                            new InputStreamReader(
                                    new ClassPathResource(path).getInputStream(),
                                    StandardCharsets.UTF_8)),
                    type);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 把json数据转成对象
     *
     * @param json json类型的数据
     * @param type 转换的类格式
     */
    public static <T> T jsonObjectToType(Object json, Class<T> type) {
        try {
            if (json instanceof String) {
                return JSONObject.parseObject((String) json, type);
            } else {
                return JSONObject.parseObject(JSON.toJSONString(json), type);
            }
        } catch (Exception e) {
            log.error("类型转换失败,数据：{},类型：{}", json, type);
            return null;
        }
    }

    /**
     * 把json数据转成对象
     *
     * @param json          json类型的数据
     * @param typeReference 转换的类格式
     */
    public static <T> T jsonObjectToType(Object json, TypeReference<T> typeReference) {
        try {
            if (json instanceof String) {
                return JSONObject.parseObject((String) json, typeReference);
            } else {
                return JSONObject.parseObject(JSON.toJSONString(json), typeReference);
            }
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 把json数据转成List
     *
     * @param json json类型的数据
     * @param type 转换的类格式
     */
    public static <T> List<T> jsonStringToArray(Object json, Class<T> type) {
        try {
            if (json instanceof String) {
                return JSONArray.parseArray((String) json, type);
            } else {
                return JSONArray.parseArray(JSON.toJSONString(json), type);
            }
        } catch (Exception e) {
            return null;
        }
    }

    public static <T> String toJson(T data) {
        return JSON.toJSONString(data);
    }


    /**
     * 把json解析成map，如果map内部的value存在jsonString，继续解析
     *
     * @param json
     * @return
     * @throws Exception
     */
    public static Map<String, Object> jsonToMap(@ApiNotNull String json){
        Map<String, Object> map = Optional
                .ofNullable(jsonObjectToType(json, new TypeReference<Map<String, Object>>() {
                }))
                .orElseThrow(() -> new ProgramException("类型转换异常"));
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object obj = entry.getValue();
            if (obj instanceof String) {
                String str = (String) obj;
                if (str.startsWith("[")) {
                    List<?> list = jsonToList(str);
                    map.put(entry.getKey(), list);
                } else if (str.startsWith("{")) {
                    Map<String, Object> mapRecursion = jsonToMap(str);
                    map.put(entry.getKey(), mapRecursion);
                }
            }
        }
        return map;
    }

    /**
     * 把json解析成list，如果list内部的元素存在jsonString，继续解析
     *
     * @param json
     * @return
     * @throws Exception
     */
    private static List<Object> jsonToList(@ApiNotNull String json) {
        List<Object> list = Optional
                .ofNullable(jsonObjectToType(json, new TypeReference<List<Object>>() {
                }))
                .orElseThrow(() -> new ProgramException("类型转换异常"));
        for (Object obj : list) {
            if (obj instanceof String) {
                String str = (String) obj;
                if (str.startsWith("[")) {
                    obj = jsonToList(str);
                } else if (obj.toString().startsWith("{")) {
                    obj = jsonToMap(str);
                }
            }
        }
        return list;
    }
}

